package com.coocaa.ops.common.tool.exception;

import com.coocaa.ops.common.tool.json.JsonUtil;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author tangminghong
 * @date 2020-06-10 17:34
 */
public class ExceptionUtil {


    private ExceptionUtil() {
    }

    /**
     * @param e
     * @return
     */
    public static String getErrorPrintLog(String bizName, Exception e) {
        if (e instanceof BusinessException) {
            BusinessException businessException = (BusinessException) e;
            return getErrorPrintLog(bizName, businessException.getErrMsg(), businessException.getErrOpData(), null);
        }
        return getErrorPrintLog(bizName, e.getMessage(), null, getStackTraceAsString(e));
    }
    public static String getErrorPrintLog(String bizName, Object opParams, Exception e) {
        return getErrorPrintLog(bizName, e.getMessage(), opParams, ExceptionUtil.getStackTraceAsString(e));
    }

    public static String getErrorPrintLog(String bizName, String msg) {
        return getErrorPrintLog(bizName, msg, null, null);
    }

    public static String getErrorPrintLog(String bizName, String msg, String stackInfo) {
        return getErrorPrintLog(bizName, msg, null, stackInfo);

    }

    public static String getErrorPrintLog(String bizName, String msg, Exception e) {
        return getErrorPrintLog(bizName, msg, null, getStackTraceAsString(e));
    }

    public static String getErrorPrintLog(String bizName, String msg, Object opParams) {
        return getErrorPrintLog(bizName, msg, opParams, null);
    }

    public static String getErrorPrintLog(String bizName, String msg, Object opParams, String stackInfo) {
        String opParamsStr = opParams == null ? "" : JsonUtil.obj2Json(opParams);
        stackInfo = stackInfo == null ? "" : stackInfo;
        StringBuilder finalInfo = new StringBuilder();
        finalInfo.append(bizName).append(" ")
                .append(msg).append(" ")
                .append("[").append(opParamsStr).append("]").append(" ")
                .append("[").append(stackInfo).append("]")
        ;
        return finalInfo.toString();
    }

    public static String getStackTraceAsString(Throwable e) {
        return getStackTraceAsString(e, 5);
    }

    public static String getStackTraceAsString(Throwable e, int line) {
        if (e == null) {
            return "";
        } else {
            StringWriter stringWriter = new StringWriter();
            e.printStackTrace(new PrintWriter(stringWriter, true));
            int index = getIndex(stringWriter.toString(), line, "\\n\\t");
            if (index != 0) {
                String st = stringWriter.toString().substring(0, index);
                return st;
            } else {
                return stringWriter.toString();
            }
        }
    }

    @SafeVarargs
    public static boolean isCausedBy(Exception ex, Class... causeExceptionClasses) {
        for (Throwable cause = ex.getCause(); cause != null; cause = cause.getCause()) {
            Class[] var3 = causeExceptionClasses;
            int var4 = causeExceptionClasses.length;

            for (int var5 = 0; var5 < var4; ++var5) {
                Class<? extends Exception> causeClass = var3[var5];
                if (causeClass.isInstance(cause)) {
                    return true;
                }
            }
        }

        return false;
    }


    /**
     * 用于减少堆栈打印信息
     *
     * @param string 字符串
     * @param i      第i次出现
     * @param str    子字符串
     * @return
     */
    public static int getIndex(String string, int i, String str) {
        //这里是获取符号第i次出现的下标
        try {
            Matcher slashMatcher = Pattern.compile(str).matcher(string);
            int mIdx = 0;
            while (slashMatcher.find()) {
                mIdx++;
                //当"/"符号第i次出现的位置
                if (mIdx == i) {
                    break;
                }
            }
            return slashMatcher.start();
        } catch (Exception e) {
            return 0;
        }
    }
}
